package com.sg.business.model;

import java.util.Calendar;
import java.util.Date;
import java.util.List;

import org.bson.types.ObjectId;

import com.mobnut.commons.util.Utils;
import com.mobnut.db.model.ModelService;
import com.mobnut.db.model.PrimaryObject;
import com.mongodb.BasicDBObject;
import com.mongodb.DBCollection;

public class ProjectStep extends PrimaryObject implements IProjectRelative,
		ISchedule {

	public static final String EDITOR = "project.projectstep.editor";

	@Override
	public Project getProject() {
		ObjectId projectId = getProjectId();
		if (projectId != null) {
			return ModelService.createModelObject(Project.class, projectId);
		}
		return null;
	}

	public ObjectId getProjectId() {
		return getObjectIdValue(F_PROJECT_ID);
	}

	@Override
	public Date getActualStart() {
		return getDateValue(F_ACTUAL_START);
	}

	@Override
	public Date getActualFinish() {
		return getDateValue(F_ACTUAL_FINISH);
	}

	@Override
	public Date getPlanStart() {
		return getDateValue(F_PLAN_START);
	}

	@Override
	public Date getPlanFinish() {
		return getDateValue(F_PLAN_FINISH);
	}

	@Override
	public Integer getActualDuration() {
		Date af = getActualFinish();
		Date as = getActualStart();
		if (as == null) {
			return null;
		}
		if (af == null) {
			af = new Date();
		}
		Calendar _af = Utils.getDayBegin(af);
		Calendar _as = Utils.getDayBegin(as);
		int days1 = new Long(_af.getTimeInMillis() / 8640000).intValue();
		int days2 = new Long(_as.getTimeInMillis() / 8640000).intValue();
		return days1 - days2;
	}

	@Override
	public Integer getPlanDuration() {
		Date af = getPlanFinish();
		Date as = getPlanStart();
		if (as == null || af == null) {
			return null;
		}
		Calendar _af = Utils.getDayBegin(af);
		Calendar _as = Utils.getDayBegin(as);
		int days1 = new Long(_af.getTimeInMillis() / (1000 * 60 * 60 * 24))
				.intValue();
		int days2 = new Long(_as.getTimeInMillis() / (1000 * 60 * 60 * 24))
				.intValue();
		return days1 - days2;
	}

	public void doSetUpPlanStart(Date planStart) {
		if (planStart != null) {
			Date update = null;
			Date start = getPlanStart();
			if (start == null) {
				update = planStart;
			} else {
				List<PrimaryObject> startWorks = getStartWorks();
				if (startWorks != null && startWorks.size() > 0) {
					for (PrimaryObject po : startWorks) {
						Date workPlanStart = ((Work) po).getPlanStart();
						if (workPlanStart != null
								&& workPlanStart.after(planStart)) {
							planStart = workPlanStart;
						}
					}
					update = planStart;
				} else {
					update = null;
				}
			}
			if (update != null) {
				DBCollection col = getCollection();
				col.update(new BasicDBObject().append(F__ID, get_id()),
						new BasicDBObject().append("$set", new BasicDBObject()
								.append(F_PLAN_START, update)));
			}
		}
	}

	public void doSetUpPlanFinish(Date planFinish) {
		if (planFinish != null) {
			Date update = null;
			Date finish = getPlanFinish();
			if (finish == null) {
				update = planFinish;
			} else {
				List<PrimaryObject> finishWorks = getFinishWorks();
				if (finishWorks != null && finishWorks.size() > 0) {
					for (PrimaryObject po : finishWorks) {
						Date workPlanFinish = ((Work) po).getPlanFinish();
						if (workPlanFinish != null
								&& workPlanFinish.after(planFinish)) {
							planFinish = workPlanFinish;
						}
					}
					update = planFinish;
				} else {
					update = null;
				}
			}
			if (update != null) {
				DBCollection col = getCollection();
				col.update(new BasicDBObject().append(F__ID, get_id()),
						new BasicDBObject().append("$set", new BasicDBObject()
								.append(F_PLAN_FINISH, update)));
			}
		}
	}

	public void doSetUpActualStart() {
		Date actualStart = getActualStart();
		if (actualStart == null) {
			DBCollection col = getCollection();
			col.update(new BasicDBObject().append(F__ID, get_id()),
					new BasicDBObject().append("$set", new BasicDBObject()
							.append(F_ACTUAL_START, Calendar.getInstance()
									.getTime())));
		}
	}

	public void doSetUpActualFinish() {
		Date actualFinish = getActualFinish();
		if (actualFinish == null) {
			DBCollection col = getCollection();
			col.update(new BasicDBObject().append(F__ID, get_id()),
					new BasicDBObject().append("$set", new BasicDBObject()
							.append(F_ACTUAL_FINISH, Calendar.getInstance()
									.getTime())));
		}
	}

	public List<PrimaryObject> getFinishWorks() {
		return getRelationById(F__ID, Work.F_PROJECT_STEP_FINISH, Work.class);
	}

	public List<PrimaryObject> getStartWorks() {
		return getRelationById(F__ID, Work.F_PROJECT_STEP_START, Work.class);
	}
}
